package com.hnit.applet.utils;

import com.hnit.applet.config.MinioPropertiesConfig;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import org.apache.commons.io.IOUtils;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.activation.MimetypesFileTypeMap;
import javax.annotation.Resource;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

/**
 * @author zwj
 * @date 2022/4/21
 * @description TODO minio工具类
 */
@Component
@EnableConfigurationProperties(MinioPropertiesConfig.class)
public class MinioUtil {

    @Resource
    private MinioPropertiesConfig minioPropertiesConfig;

    @Resource
    private MinioClient minioClient;

    /**
     * 上传文件
     *
     * @param file     文件
     * @param fileName 文件名
     */
    public void upload(MultipartFile file, String fileName) {
        InputStream in = null;
        try {
            in = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioPropertiesConfig.getBucketName())
                    .object(fileName)
                    .stream(in, in.available(), -1)
                    .contentType(file.getContentType())
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 上传文件
     *
     * @param file     文件
     * @param fileName 文件名
     */
    public void upload(File file, String fileName) {
        InputStream in = null;
        try {
            String contentType = new MimetypesFileTypeMap().getContentType(file);
            in = new FileInputStream(file);
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioPropertiesConfig.getBucketName())
                    .object(fileName)
                    .stream(in, in.available(), -1)
                    .contentType(contentType)
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 下载文件
     *
     * @param objectName 文件名称
     *
     * @return 字节数组
     */
    public byte[] download(String objectName) {
        InputStream in = null;
        try {
            in = minioClient.getObject(GetObjectArgs.builder().bucket(minioPropertiesConfig.getBucketName()).object(objectName).build());
            return IOUtils.toByteArray(in);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    /**
     * 删除文件
     *
     * @param objectName 存储桶里的对象名称
     */
    public void removeObject(String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioPropertiesConfig.getBucketName()).object(objectName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 从objectName指定的对象中将数据拷贝到destObjectName指定的对象。
     *
     * @param sourceObject 来源文件
     * @param aimObject    目标文件
     */
    public void copyObject(String sourceObject, String aimObject) {
        try {
            minioClient.copyObject(CopyObjectArgs.builder().bucket(minioPropertiesConfig.getBucketName()).object(aimObject).source(CopySource.builder().bucket(minioPropertiesConfig.getBucketName()).object(sourceObject).build()).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载，即使其所在的存储桶是私有的
     *
     * @param objectName 文件名
     *
     * @return url
     */
    public String presignedGetObject(String objectName) {
        String url = null;
        try {
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(minioPropertiesConfig.getBucketName()).object(objectName).expiry(minioPropertiesConfig.getExpiry(), TimeUnit.HOURS).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return url;
    }

    /**
     * 查询文件是否存在,不存在的话抛出异常
     *
     * @param objectName 文件名
     *
     * @return 文件信息
     */
    public StatObjectResponse statObject(String objectName) throws ServerException, InsufficientDataException,
            ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException,
            InvalidResponseException, XmlParserException, InternalException {
        return minioClient.statObject(StatObjectArgs.builder().bucket(minioPropertiesConfig.getBucketName()).object(objectName).build());
    }
}
